package com.wpzf.zxhc.controller;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.crypto.symmetric.SM4;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.wpzf.common.core.web.domain.AjaxResult;
import com.wpzf.common.log.annotation.Log;
import com.wpzf.common.log.enums.BusinessType;
import org.junit.Test;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.time.Instant;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/gty")
public class WpzfHcGTYController
{
    String privateKey = "E4F22E79D141717AA63231A9DF53F4062545F17950BCB87B184B0128C6CC494E";
    String publicKey = "04D33B320ED4819E4BC0CBE579EA8C1EC5D23A63922C3A62C7DF46EE800777363B3F97B3E103D47933052F793BA1C55EAB5826B58A886D9FFE2565F3C8EFCCD8B1";
    String gtypublicKey = "04CF7CAE31B5130D1D5D1AC1DC2778D94533868A8D57FC02BBD97B688E07145DAAA96462DC83D9F348261F738D51C049770C43BA53B584917C9E30C6221B737CDD";

    public String createToken()
    {
        String privateKey = "E4F22E79D141717AA63231A9DF53F4062545F17950BCB87B184B0128C6CC494E";
        String publicKey = "04D33B320ED4819E4BC0CBE579EA8C1EC5D23A63922C3A62C7DF46EE800777363B3F97B3E103D47933052F793BA1C55EAB5826B58A886D9FFE2565F3C8EFCCD8B1";

        //SM2
        SM2 sm2 = new SM2(privateKey, publicKey);
        sm2.usePlainEncoding();
        //SM2 token生成
        String certCode = "API32_YXK33YEGLXMUVMOYEQ43JWE4EU";
        long timestamp = System.currentTimeMillis();
        //拼接待签名数据
        String needSignData = certCode + timestamp;
        byte[] needSignDataByte = needSignData.getBytes(StandardCharsets.UTF_8);
        //签名
        byte[] signData = sm2.sign(needSignDataByte);
        //签名
        String signDataHex = HexUtil.encodeHexStr(signData);

        String signDataBase64 = cn.hutool.core.codec.Base64.encode(signData);
        //生成token
        String token = certCode + "." + timestamp + "." + signDataBase64;

        //SM2 token验证
        boolean rst1 = sm2.verify(needSignDataByte, signData);
        boolean rst2 = sm2.verify(needSignDataByte, HexUtil.decodeHex(signDataHex));
        boolean rst3 = sm2.verify(needSignDataByte, Base64.decode(signDataBase64));
        System.out.println("verify result:" + rst3);
        return token;
    }

    //DB包 先注册接口  再订阅 订阅后主动推送 间隔6个小时 增量推送
    @Log(title = "接口注册/更新", businessType = BusinessType.OTHER)
    @RequestMapping(value = "/RegistService", method = RequestMethod.POST)
    public AjaxResult  RegistService()
    {
        //(1)生成适用于SM4算法的随机密钥C sm4Key（128bit）
        byte[] keyC = SecureUtil.generateKey("SM4").getEncoded();

        //(2)使用密钥C，采用SM4算法对接口参数进行加密并编译成base64编码
        String data = "{\"regioncode\": \"000000\",\"serviceurl\": \"http://wpzfzhhc.totop.net.cn:8007\",\n" +
                "\"contacts\": \"卫片执法智慧核查年度卫片\",\n" +
                "\"phone\": \"14210319140\"}";
        System.out.println("原始参数:" + data);

        byte[] dataByte = data.getBytes(StandardCharsets.UTF_8);

        SM4 sm4 = new SM4(keyC);
        byte[] sm4EncryptDataByte = sm4.encrypt(dataByte);
        String params=Base64.encode(sm4EncryptDataByte);
        System.out.println("参数加密后:" + Base64.encode(sm4EncryptDataByte));

        //(3)使用服务提供方的公钥B，采用SM2加密算法对密钥C进行加密并编码成base64写入Header的x-lc-secret中
        SM2 sm2 = new SM2(null,gtypublicKey);
        sm2.usePlainEncoding();
        byte[] sm2EncryptDataByte = sm2.encrypt(keyC, KeyType.PublicKey);
        String secret=Base64.encode(sm2EncryptDataByte);
        System.out.println("输入secret:" + secret);

        //(4)生成token
        String token=createToken();
        System.out.println("输入token:" + token);

        //(5)发送请求，获取返回值
        String postURL = "https://openapi.landcloud.org.cn/v1/DataExchange/RegistService";
        try {
            URL url = new URL(postURL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("Charset", "utf-8");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            conn.setRequestProperty("Content-Type", "application/json;charset=utf-8 ");
            conn.setRequestProperty("x-lc-token", token);
            conn.setRequestProperty("x-lc-secret", secret);

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setConnectTimeout(2000);
            conn.setReadTimeout(2000);
            //获取URLConnection对象对应的输出流
            OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
            out.write(params);
            out.flush();

            InputStream is = conn.getInputStream();
            int count = 0;
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            while ((count = is.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, count);
            }
            byte[] datas = byteArrayOutputStream.toByteArray();
            byteArrayOutputStream.close();
            is.close();
            conn.disconnect();
            String rest = new String(datas, 0, datas.length, "utf-8");
            JSONObject obj = JSONObject.parseObject(rest);

            // 获取响应头
            Map<String, List<String>> headerFields = conn.getHeaderFields();
//            for (Map.Entry<String, java.util.List<String>> header : headerFields.entrySet())
//            {
//                System.out.println(header.getKey() + ": " + header.getValue());
//            }
            //(6)从返回头获取
            String resecret = headerFields.get("x-lc-secret").get(0);
            System.out.println("输出结果resecret:" + resecret);


            sm2 = new SM2(privateKey, publicKey);
            sm2.usePlainEncoding();
            //SM2 解密SM4密钥
            byte[] decode = sm2.decrypt(resecret, KeyType.PrivateKey);
            //SM4解密内容
            sm4 = new SM4(decode);
            if (obj.get("data") != null) {
                byte[] sm4DataByte = sm4.decrypt(obj.get("data").toString());
                System.out.println("data解密:" + new String(sm4DataByte, StandardCharsets.UTF_8));
                return AjaxResult.success("获取成功", new String(sm4DataByte, StandardCharsets.UTF_8));
            }
            else {
                return AjaxResult.error("获取失败,返回结果data为空");
            }
        }
        catch (Exception ex)
        {
            return AjaxResult.error("获取失败", ex.toString());
        }
    }


    @Log(title = "数据订阅/更新", businessType = BusinessType.OTHER)
    @RequestMapping(value = "/RegistDataCode", method = RequestMethod.POST)
    public AjaxResult RegistDataCode(@RequestBody Map<String, Object> parm)
    {
        //(1)生成适用于SM4算法的随机密钥C sm4Key（128bit）
        byte[] keyC = SecureUtil.generateKey("SM4").getEncoded();
        //String include_xzqdms=parm.get("xzqdms").toString();
        //(2)使用密钥C，采用SM4算法对接口参数进行加密并编译成base64编码
        String data = "{\"code\": \"WPZFNDTB2024\"}";
        System.out.println("原始参数:" + data);

        byte[] dataByte = data.getBytes(StandardCharsets.UTF_8);

        SM4 sm4 = new SM4(keyC);
        byte[] sm4EncryptDataByte = sm4.encrypt(dataByte);
        String params=Base64.encode(sm4EncryptDataByte);
        System.out.println("参数加密后:" + Base64.encode(sm4EncryptDataByte));


        //(3)使用服务提供方的公钥B，采用SM2加密算法对密钥C进行加密并编码成base64写入Header的x-lc-secret中
        SM2 sm2 = new SM2(null,gtypublicKey);
        sm2.usePlainEncoding();
        byte[] sm2EncryptDataByte = sm2.encrypt(keyC, KeyType.PublicKey);
        String secret=Base64.encode(sm2EncryptDataByte);
        System.out.println("输入secret:" + secret);

        //(4)生成token
        String token=createToken();
        System.out.println("输入token:" + token);

        //(5)发送请求，获取返回值
        String postURL = "https://openapi.landcloud.org.cn/v1/DataExchange/RegistDataCode";
        try {
            URL url = new URL(postURL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("Charset", "utf-8");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            conn.setRequestProperty("Content-Type", "application/json;charset=utf-8 ");
            conn.setRequestProperty("x-lc-token", token);
            conn.setRequestProperty("x-lc-secret", secret);
            conn.setRequestProperty("x-lc-datacode", "WPZFNDTB2024");

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setConnectTimeout(2000);
            conn.setReadTimeout(2000);
            //获取URLConnection对象对应的输出流
            OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
            out.write(params);
            out.flush();

            InputStream is = conn.getInputStream();
            int count = 0;
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            while ((count = is.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, count);
            }
            byte[] datas = byteArrayOutputStream.toByteArray();
            byteArrayOutputStream.close();
            is.close();
            conn.disconnect();
            String rest = new String(datas, 0, datas.length, "utf-8");
            JSONObject obj = JSONObject.parseObject(rest);

            // 获取响应头
            Map<String, java.util.List<String>> headerFields = conn.getHeaderFields();
//            for (Map.Entry<String, java.util.List<String>> header : headerFields.entrySet())
//            {
//                System.out.println(header.getKey() + ": " + header.getValue());
//            }
            //(6)从返回头获取
            String resecret = headerFields.get("x-lc-secret").get(0);
            System.out.println("输出结果resecret:" + resecret);


            sm2 = new SM2(privateKey, publicKey);
            sm2.usePlainEncoding();
            //SM2 解密SM4密钥
            byte[] decode = sm2.decrypt(resecret, KeyType.PrivateKey);
            //SM4解密内容
            sm4 = new SM4(decode);
            if (obj.get("data") != null) {
                byte[] sm4DataByte = sm4.decrypt(obj.get("data").toString());
                System.out.println("data解密结果:" + new String(sm4DataByte, StandardCharsets.UTF_8));
                return AjaxResult.success("获取成功", new String(sm4DataByte, StandardCharsets.UTF_8));
            }
            else {
                return AjaxResult.error("获取失败,返回结果data为空");
            }
        }
        catch (Exception ex)
        {
            return AjaxResult.error("获取失败", ex.toString());
        }

    }



    @Log(title = "上报DB数据订阅", businessType = BusinessType.OTHER)
    @RequestMapping(value = "/RegistUploadDataCode", method = RequestMethod.POST)
    public AjaxResult RegistUploadDataCode(@RequestBody Map<String, Object> parm)
    {
        //(1)生成适用于SM4算法的随机密钥C sm4Key（128bit）
        byte[] keyC = SecureUtil.generateKey("SM4").getEncoded();
        //String include_xzqdms=parm.get("xzqdms").toString();
        //(2)使用密钥C，采用SM4算法对接口参数进行加密并编译成base64编码
        String data = "{\"code\": \"WPZFNDTB2024_RECV\"}";
        System.out.println("原始参数:" + data);

        byte[] dataByte = data.getBytes(StandardCharsets.UTF_8);

        SM4 sm4 = new SM4(keyC);
        byte[] sm4EncryptDataByte = sm4.encrypt(dataByte);
        String params=Base64.encode(sm4EncryptDataByte);
        System.out.println("参数加密后:" + Base64.encode(sm4EncryptDataByte));


        //(3)使用服务提供方的公钥B，采用SM2加密算法对密钥C进行加密并编码成base64写入Header的x-lc-secret中
        SM2 sm2 = new SM2(null,gtypublicKey);
        sm2.usePlainEncoding();
        byte[] sm2EncryptDataByte = sm2.encrypt(keyC, KeyType.PublicKey);
        String secret=Base64.encode(sm2EncryptDataByte);
        System.out.println("输入secret:" + secret);

        //(4)生成token
        String token=createToken();
        System.out.println("输入token:" + token);

        //(5)发送请求，获取返回值
        String postURL = "https://openapi.landcloud.org.cn/v1/DataExchange/RegistDataCode";
        try {
            URL url = new URL(postURL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("Charset", "utf-8");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            conn.setRequestProperty("Content-Type", "application/json;charset=utf-8 ");
            conn.setRequestProperty("x-lc-token", token);
            conn.setRequestProperty("x-lc-secret", secret);
            conn.setRequestProperty("x-lc-datacode", "WPZFNDTB2024_RECV");

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setConnectTimeout(2000);
            conn.setReadTimeout(2000);
            //获取URLConnection对象对应的输出流
            OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
            out.write(params);
            out.flush();

            InputStream is = conn.getInputStream();
            int count = 0;
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            while ((count = is.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, count);
            }
            byte[] datas = byteArrayOutputStream.toByteArray();
            byteArrayOutputStream.close();
            is.close();
            conn.disconnect();
            String rest = new String(datas, 0, datas.length, "utf-8");
            JSONObject obj = JSONObject.parseObject(rest);

            // 获取响应头
            Map<String, java.util.List<String>> headerFields = conn.getHeaderFields();
//            for (Map.Entry<String, java.util.List<String>> header : headerFields.entrySet())
//            {
//                System.out.println(header.getKey() + ": " + header.getValue());
//            }
            //(6)从返回头获取
            String resecret = headerFields.get("x-lc-secret").get(0);
            System.out.println("输出结果resecret:" + resecret);


            sm2 = new SM2(privateKey, publicKey);
            sm2.usePlainEncoding();
            //SM2 解密SM4密钥
            byte[] decode = sm2.decrypt(resecret, KeyType.PrivateKey);
            //SM4解密内容
            sm4 = new SM4(decode);
            if (obj.get("data") != null) {
                byte[] sm4DataByte = sm4.decrypt(obj.get("data").toString());
                System.out.println("data解密结果:" + new String(sm4DataByte, StandardCharsets.UTF_8));
                return AjaxResult.success("获取成功", new String(sm4DataByte, StandardCharsets.UTF_8));
            }
            else {
                return AjaxResult.error("获取失败,返回结果data为空");
            }
        }
        catch (Exception ex)
        {
            return AjaxResult.error("获取失败", ex.toString());
        }

    }



    @Log(title = "上传文件地址获取接口", businessType = BusinessType.OTHER)
    @RequestMapping(value = "/getUploadFilePath", method = RequestMethod.POST)
    public AjaxResult getUploadFilePath(@RequestBody Map<String, Object> parm)
    {
        //(1)生成适用于SM4算法的随机密钥C sm4Key（128bit）
        byte[] keyC = SecureUtil.generateKey("SM4").getEncoded();
        //String include_xzqdms=parm.get("xzqdms").toString();
        //(2)使用密钥C，采用SM4算法对接口参数进行加密并编译成base64编码
        String data = "{\"code\": \"WPZFNDTB2024_RECV\",\n" +
                "\"regioncode\":\"340827\",\n" +
                "\"filenames\": [\"340827.db\"]}";
        System.out.println("原始参数:" + data);

        byte[] dataByte = data.getBytes(StandardCharsets.UTF_8);
        SM4 sm4 = new SM4(keyC);
        byte[] sm4EncryptDataByte = sm4.encrypt(dataByte);
        String params=Base64.encode(sm4EncryptDataByte);
        System.out.println("参数加密后:" + Base64.encode(sm4EncryptDataByte));


        //(3)使用服务提供方的公钥B，采用SM2加密算法对密钥C进行加密并编码成base64写入Header的x-lc-secret中
        SM2 sm2 = new SM2(null,gtypublicKey);
        sm2.usePlainEncoding();
        byte[] sm2EncryptDataByte = sm2.encrypt(keyC, KeyType.PublicKey);
        String secret=Base64.encode(sm2EncryptDataByte);
        System.out.println("输入secret:" + secret);

        //(4)生成token
        String token=createToken();
        System.out.println("输入token:" + token);

        //(5)发送请求，获取返回值
        String postURL = "https://openapi.landcloud.org.cn/v1/DataExchange/getUploadFilePath";
        try {
            URL url = new URL(postURL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("Charset", "utf-8");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            conn.setRequestProperty("Content-Type", "application/json;charset=utf-8 ");
            conn.setRequestProperty("x-lc-token", token);
            conn.setRequestProperty("x-lc-secret", secret);
            conn.setRequestProperty("x-lc-datacode", "WPZFNDTB2024_RECV");

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setConnectTimeout(2000);
            conn.setReadTimeout(2000);
            //获取URLConnection对象对应的输出流
            OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
            out.write(params);
            out.flush();

            InputStream is = conn.getInputStream();
            int count = 0;
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            while ((count = is.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, count);
            }
            byte[] datas = byteArrayOutputStream.toByteArray();
            byteArrayOutputStream.close();
            is.close();
            conn.disconnect();
            String rest = new String(datas, 0, datas.length, "utf-8");
            JSONObject obj = JSONObject.parseObject(rest);

            // 获取响应头
            Map<String, java.util.List<String>> headerFields = conn.getHeaderFields();
            String resecret = headerFields.get("x-lc-secret").get(0);
            System.out.println("输出结果resecret:" + resecret);
            sm2 = new SM2(privateKey, publicKey);
            sm2.usePlainEncoding();
            //SM2 解密SM4密钥
            byte[] decode = sm2.decrypt(resecret, KeyType.PrivateKey);
            //SM4解密内容
            sm4 = new SM4(decode);
            if (obj.get("data") != null) {
                byte[] sm4DataByte = sm4.decrypt(obj.get("data").toString());
                System.out.println("data解密结果:" + new String(sm4DataByte, StandardCharsets.UTF_8));

                String result=new String(sm4DataByte, StandardCharsets.UTF_8);
                JSONArray arraylist = JSONObject.parseArray(result);
                if(arraylist.size()>0) {
                    for (int i = 0; i < arraylist.size(); i++) {
                        JSONObject jsonObject = arraylist.getJSONObject(i);
                        String writeurl = jsonObject.getString("writeurl");//DB包写入地址
                        String readurl = jsonObject.getString("readurl");//DB包读取地址

                        JSONObject contenttypeObject = JSONObject.parseObject(jsonObject.getString("header"));
                        String contenttype = contenttypeObject.get("content-type").toString();
                        URL uploadurl = new URL(writeurl);
                        boolean flag = uploadObject(uploadurl, "D:/2222/340827.db", contenttype);
                        if (flag) //DB文件上传成功
                        {
                            postURL = "https://openapi.landcloud.org.cn/v1/DataExchange/pushDataPackage";


                        } else {
                            return AjaxResult.error("DB上传失败");
                        }
                    }
                }

                return AjaxResult.success("获取成功", new String(sm4DataByte, StandardCharsets.UTF_8));
            }
            else {
                return AjaxResult.error("获取失败,返回结果data为空");
            }
        }
        catch (Exception ex)
        {
            return AjaxResult.error("获取失败", ex.toString());
        }

    }


    //上报
    @Log(title = "提交接口", businessType = BusinessType.OTHER)
    @RequestMapping(value = "/pushDataPackage", method = RequestMethod.POST)
    public AjaxResult pushDataPackage(@RequestBody Map<String, Object> parm)
    {
        //(1)生成适用于SM4算法的随机密钥C sm4Key（128bit）
        byte[] keyC = SecureUtil.generateKey("SM4").getEncoded();
        //(2)使用密钥C，采用SM4算法对接口参数进行加密并编译成base64编码
        String regioncode="340827";
        String version="1";
        String password="";
        int size=100;
        int tbcount=10;
        int attachment_count=10;
        long utcTimestampSeconds = Instant.now().getEpochSecond();
        String relateurl="http://gdhc-gj-012035.obs.cn-north-1.myhuaweicloud.com/Temp/2024/202412/WPZFNDTB2024_RECV/340827/181540/340827.db";
        String sign="0D64E549FD6000FC190CDCDECE0AE8FEBA30E2D487E529D8C3958F4EDE9E61F3B1D2BC7D406BED2FB9A9B54AB86CD9DDFD93EE0FAB5102F410A196E85F70B6AF";
        String hash=calculateFileHash("D:/2222/340827.db");//文件的哈希值是对文件内容采用国密SM3计算哈希值
        String data = "{\"code\": \"WPZFNDTB2024_RECV\"," +
                       "\"regioncode\":\"" + regioncode + "\"," +
                       "\"version\":\"" + version + "\"," +
                       "\"password\":\"" + password + "\"," +
                       "\"size\":\"" + size + "\"," +
                       "\"count\":\"" + tbcount + "\"," +
                       "\"attachment_count\":\"" + attachment_count + "\"," +
                       "\"extension\":\"db\"," +
                       "\"hash\":\"" + hash + "\"," +
                       "\"timestamp\":\"" + utcTimestampSeconds + "\"," +
                       "\"url\":\"" + relateurl + "\"," +
                       "\"sign\":\"" + sign + "\"}";

        System.out.println("原始参数:" + data);

        byte[] dataByte = data.getBytes(StandardCharsets.UTF_8);

        SM4 sm4 = new SM4(keyC);
        byte[] sm4EncryptDataByte = sm4.encrypt(dataByte);
        String params=Base64.encode(sm4EncryptDataByte);
        System.out.println("参数加密后:" + Base64.encode(sm4EncryptDataByte));


        //(3)使用服务提供方的公钥B，采用SM2加密算法对密钥C进行加密并编码成base64写入Header的x-lc-secret中
        SM2 sm2 = new SM2(null,gtypublicKey);
        sm2.usePlainEncoding();
        byte[] sm2EncryptDataByte = sm2.encrypt(keyC, KeyType.PublicKey);
        String secret=Base64.encode(sm2EncryptDataByte);
        System.out.println("输入secret:" + secret);

        //(4)生成token
        String token=createToken();
        System.out.println("输入token:" + token);

        //(5)发送请求，获取返回值
        String postURL = "https://openapi.landcloud.org.cn/v1/DataExchange/pushDataPackage";
        try {
            URL url = new URL(postURL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("Charset", "utf-8");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            conn.setRequestProperty("Content-Type", "application/json;charset=utf-8 ");
            conn.setRequestProperty("x-lc-token", token);
            conn.setRequestProperty("x-lc-secret", secret);
            conn.setRequestProperty("x-lc-datacode", "WPZFNDTB2024_RECV");

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setConnectTimeout(2000);
            conn.setReadTimeout(2000);
            //获取URLConnection对象对应的输出流
            OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
            out.write(params);
            out.flush();

            InputStream is = conn.getInputStream();
            int count = 0;
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            while ((count = is.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, count);
            }
            byte[] datas = byteArrayOutputStream.toByteArray();
            byteArrayOutputStream.close();
            is.close();
            conn.disconnect();
            String rest = new String(datas, 0, datas.length, "utf-8");
            JSONObject obj = JSONObject.parseObject(rest);

            // 获取响应头
            Map<String, java.util.List<String>> headerFields = conn.getHeaderFields();
//            for (Map.Entry<String, java.util.List<String>> header : headerFields.entrySet())
//            {
//                System.out.println(header.getKey() + ": " + header.getValue());
//            }
            //(6)从返回头获取
            String resecret = headerFields.get("x-lc-secret").get(0);
            System.out.println("输出结果resecret:" + resecret);


            sm2 = new SM2(privateKey, publicKey);
            sm2.usePlainEncoding();
            //SM2 解密SM4密钥
            byte[] decode = sm2.decrypt(resecret, KeyType.PrivateKey);
            //SM4解密内容
            sm4 = new SM4(decode);
            if (obj.get("data") != null) {
                byte[] sm4DataByte = sm4.decrypt(obj.get("data").toString());
                System.out.println("data解密结果:" + new String(sm4DataByte, StandardCharsets.UTF_8));
                return AjaxResult.success("获取成功", new String(sm4DataByte, StandardCharsets.UTF_8));
            }
            else {
                return AjaxResult.error("获取失败,返回结果data为空");
            }
        }
        catch (Exception ex)
        {
            return AjaxResult.error("获取失败", ex.toString());
        }

    }


    public static String calculateFileHash(String filePath) {
        try {
            Security.addProvider(new BouncyCastleProvider());
            MessageDigest md = MessageDigest.getInstance("SM3");
            FileInputStream fis = new FileInputStream(filePath);
            byte[] buffer = new byte[8192];
            int len;
            while ((len = fis.read(buffer)) != -1) {
                md.update(buffer, 0, len);
            }
            fis.close();

            byte[] hash = md.digest();

            StringBuilder sb = new StringBuilder();
            for (byte b : hash) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static boolean uploadObject(URL presignedUrl, String objectLocalPath, String contentType)
    {
        BufferedOutputStream bufferedOutputStream = null;
        BufferedInputStream bufferedInputStream = null;
        try {
            HttpURLConnection httpURLConnection =
                    (HttpURLConnection) presignedUrl.openConnection();
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setRequestProperty("Content-Type", contentType);
            httpURLConnection.setRequestMethod("PUT");
            bufferedOutputStream = new
                    BufferedOutputStream(httpURLConnection.getOutputStream());
            bufferedInputStream = new
                    BufferedInputStream(new FileInputStream(new File(objectLocalPath)));
            byte[] buffer = new byte[1024];
            int length = bufferedInputStream.read(buffer);
            while (length > 0) {
                bufferedOutputStream.write(buffer);
                length = bufferedInputStream.read(buffer);
            }
            bufferedOutputStream.flush();
            bufferedOutputStream.close();
            if(httpURLConnection.getResponseCode()==200)
            {
                System.out.println(httpURLConnection.getResponseCode());
                System.out.println(httpURLConnection.getResponseMessage());
                return true;
            }
            else
            {
                return false;
            }

        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            if (bufferedOutputStream != null) {
                try {
                    bufferedOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bufferedInputStream != null) {
                try {
                    bufferedInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }



    @Test
    public void createSecret()
    {
        String privateKey = "E4F22E79D141717AA63231A9DF53F4062545F17950BCB87B184B0128C6CC494E";
        String publicKey = "04D33B320ED4819E4BC0CBE579EA8C1EC5D23A63922C3A62C7DF46EE800777363B3F97B3E103D47933052F793BA1C55EAB5826B58A886D9FFE2565F3C8EFCCD8B1";

        //(1)生成适用于SM4算法的随机密钥C sm4Key（128bit）
        byte[] keyC = SecureUtil.generateKey("SM4").getEncoded();
        System.out.println("SM4 Key:" + HexUtil.encodeHexStr(keyC));

        //(2)使用密钥C，采用SM4算法对接口参数进行加密并编译成base64编码
        String data = "{urls:'http://landcloud.org.cn'}";
        byte[] dataByte = data.getBytes(StandardCharsets.UTF_8);

        SM4 sm4 = new SM4(keyC);
        byte[] sm4EncryptDataByte = sm4.encrypt(dataByte);
        System.out.println("SM4 encrypt Hex:" + HexUtil.encodeHexStr(sm4EncryptDataByte));
        System.out.println("SM4 encrypt Base64:" + Base64.encode(sm4EncryptDataByte));

        //(3)使用服务提供方的公钥B，采用SM2加密算法对密钥C进行加密并编码成base64写入Header的x-lc-secret中
        SM2 sm2 = new SM2(privateKey,publicKey);
        byte[] sm2EncryptDataByte = sm2.encrypt(keyC, KeyType.PublicKey);
        System.out.println("SM2 encrypt Hex:" + HexUtil.encodeHexStr(sm2EncryptDataByte));
        System.out.println("SM2 encrypt Base64:" + Base64.encode(sm2EncryptDataByte));
    }

}
